/*
 * WarfareSimulatorView.java
 */
package prototype.phase1ui;

import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.TaskMonitor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.Timer;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import org.jdesktop.application.Application;
import prototype.adaptor.RuntimeUserFactory;
import prototype.communication.Caster;
import prototype.communication.ConnectionResource;
import prototype.communication.Listener;
import prototype.communication.Message;
import prototype.communication.Receiver;
import prototype.communication.events.CommunicationEvent;
import prototype.communication.events.CommunicationEventListener;
import prototype.persistence.ScenarioDAO;
import prototype.persistence.hibernate.HibernateDAOFactory;
import prototype.persistence.hibernate.ScenarioHibernateDAO;
import prototype.persistence.pojo.Goal;
import prototype.persistence.pojo.Scenario;
import prototype.persistence.pojo.User;
import prototype.persistence.pojo.UserHasUnit;
import prototype.phase2.ui.PrototypePhase2UIView;
import prototype.runtime.federate.RuntimeUser;

/**
 * The application's main frame.
 */
public class WarfareSimulatorView extends FrameView {

    public WarfareSimulatorView(SingleFrameApplication app) {
        super(app);

        initComponents();

        Application.getInstance(WarfareSimulator.class).addExitListener(new Application.ExitListener() {

            public boolean canExit(EventObject event) {
                safeExit();
                return true;
            }

            public void willExit(EventObject event) {
            }
        });

        // status bar initialization - message timeout, idle icon and busy animation, etc
        ResourceMap resourceMap = getResourceMap();
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new Timer(messageTimeout, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                statusMessageLabel.setText("");
            }
        });
        messageTimer.setRepeats(false);
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
                statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
            }
        });
        idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
        statusAnimationLabel.setIcon(idleIcon);
        progressBar.setVisible(false);

        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {

            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        statusAnimationLabel.setIcon(busyIcons[0]);
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(true);
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                    statusAnimationLabel.setIcon(idleIcon);
                    progressBar.setVisible(false);
                    progressBar.setValue(0);
                } else if ("message".equals(propertyName)) {
                    String text = (String) (evt.getNewValue());
                    statusMessageLabel.setText((text == null) ? "" : text);
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer) (evt.getNewValue());
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(false);
                    progressBar.setValue(value);
                }
            }
        });

    }

    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = WarfareSimulator.getApplication().getMainFrame();
            aboutBox = new WarfareSimulatorAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        WarfareSimulator.getApplication().show(aboutBox);
    }

    private void fillTree() {
        DefaultMutableTreeNode root = new DefaultMutableTreeNode(scenario.getName());
        DefaultTreeModel dtm = new DefaultTreeModel(root);
        Iterator<User> userIt = scenario.getUsers().iterator();
        while (userIt.hasNext()) {
            User user = userIt.next();
            DefaultMutableTreeNode newUserNode = new DefaultMutableTreeNode(user.getName());
            DefaultMutableTreeNode goals = new DefaultMutableTreeNode("Goals");
            DefaultMutableTreeNode units = new DefaultMutableTreeNode("Units");
            dtm.insertNodeInto(newUserNode, root, root.getChildCount());

            Iterator<Goal> goalIt = user.getGoals().iterator();
            if (goalIt.hasNext()) {
                dtm.insertNodeInto(goals, newUserNode, 0);
            }
            while (goalIt.hasNext()) {
                Goal goal = goalIt.next();
                DefaultMutableTreeNode goalNode = new DefaultMutableTreeNode(goal.getName());
                dtm.insertNodeInto(goalNode, goals, goals.getChildCount());
            }

            Iterator<UserHasUnit> unitIt = user.getUserHasUnits().iterator();
            if (unitIt.hasNext()) {
                dtm.insertNodeInto(units, newUserNode, newUserNode.getChildCount());
            }
            while (unitIt.hasNext()) {
                UserHasUnit uhu = unitIt.next();
                DefaultMutableTreeNode unitNode = new DefaultMutableTreeNode(uhu.getUnit().getName());
                dtm.insertNodeInto(unitNode, units, units.getChildCount());
            }
        }
        scenarioTree.setModel(dtm);
        scenarioTree.updateUI();
    }

    @Action
    public void stopStartListening() {
        if (listeningCheckBox.isSelected()) {
            listenButton.setText("Listen");
            listeningCheckBox.setSelected(false);
            listenButton.updateUI();
            listeningCheckBox.updateUI();
            stopListening();
        } else {
            listenButton.setText("Stop");
            listeningCheckBox.setSelected(true);
            listenButton.updateUI();
            listeningCheckBox.updateUI();
            startListening();
        }
    }

    private void stopListening() {
        if (listener != null) {
            listener.stopListening();
        }
        bindings.clear();
        connectedUsers.clear();
        updateUserList();
        updateBindingsList();
    }

    @Action
    public void loadScenario() {
        ScenarioDAO sceDao = new HibernateDAOFactory().buildScenarioDAO();
        scenario = sceDao.findAll().get(0);
        sceDao = null;
        fillTree();
    }

    private void startListening() {
        coordinator = new User();
        coordinator.setName("Coordinator");
        coordinator.setId(0);
        connectedUsers.add(coordinator.getId(), coordinator);
        updateUserList();
        ConnectionResource cr = null;
        try {
            cr = new ConnectionResource();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
        }
        int portNo;
        try {
            portNo = Integer.parseInt(portField.getText());
            cr.setPortNo(portNo);
        } catch (NumberFormatException ex) {
            portField.setText(String.valueOf(cr.getPortNo()));
        }
        listener = new Listener(cr);

        listener.addEventListener(
                new CommunicationEventListener() {

                    public void communicationEventReceived(CommunicationEvent event) {
                        listenerChecker(event);
                    }
                });
        Thread th = new Thread(listener);
        System.out.println("Running listener");
        th.start();
        System.out.println("Continuing");
    }

    public void listenerChecker(CommunicationEvent event) {
        Listener l = (Listener) event.getSource();
        if (event.getEventType() == CommunicationEvent.ConnectionLost) {
            connectedUsers.clear();
        } else if (event.getEventType() == CommunicationEvent.ServerSocketFailed) {
            stopListening();
            return;
        } else {
            for (int i = 0; i
                    < l.getReceiversSize(); i++) {
                Receiver rec = l.getReceiverAt(i);
                if (rec == null) {
                    continue;
                }
                rec.addEventListener(new CommunicationEventListener() {

                    public void communicationEventReceived(CommunicationEvent event) {
                        int i = listener.reciverAt(event.getSource());
                        if (event.getEventType() == CommunicationEvent.MessageReceived) {
                            Message m = ((Receiver) event.getSource()).getNextMessage();
                            if (m == null) {
                            } else if (m.getMessageType() == Message.JOIN) {
                                System.out.println("JOIN");
                                Message n = new Message(Message.JOIN_RES);
                                n.setMessageText("Welcome " + m.getMessageText());
                                n.setScenario(scenario);
                                Caster cast = listener.getCasterAt(i);
                                cast.castMessage(n);
                                User u = new User();
                                u.setName(m.getMessageText());
                                u.setId(new Integer(i + 1));
                                connectedUsers.add(u.getId(), u);
                            } else if (m.getMessageType() == Message.QUIT) {
                                listener.stopConnectionAt(i);
                                connectedUsers.remove(i + 1);
                            }
                        } else if (event.getEventType() == CommunicationEvent.ConnectionLost) {
                            listener.stopConnectionAt(i);
                            connectedUsers.remove(i + 1);
                        }
                        updateUserList();
                    }
                });
            }
        }
    }

    @Action
    public void safeExit() {
        if (listener != null) {
            listener.stopListening();
        }
        System.exit(0);
    }

    @Action
    public void kick() {
        int selectedUser = userList.getSelectedIndex() - 1;
        if (selectedUser <= -1) {
            return;
        }
        if (bindings.containsValue(connectedUsers.get(selectedUser + 1))) {
            Iterator<Entry<String, User>> it = bindings.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, User> entry = it.next();
                if (entry.getValue().equals(connectedUsers.get(selectedUser + 1))) {
                    bindings.remove(entry.getKey());
                    updateBindingsList();
                    break;
                }
            }
        }
        listener.getCasterAt(selectedUser).castMessage(new Message(Message.KICK));
    }

    @Action
    public void deleteBinding() {
        int selectedBinding = bindingList.getSelectedIndex();
        if (selectedBinding != -1) {
            String selectedText = (String) bindingList.getSelectedValue();
            bindings.remove(selectedText.split(" --> ")[0]);
        }

        updateBindingsList();
    }

    @Action
    public void bind() {
        if (bindings.size() >= scenario.getUsers().size() - 1) {
            return;
        }
        if (scenarioTree.getSelectionCount() != 1) {
            return;
        }

        User user = null;
        if (aiCheckBox.isSelected()) {
            user = new User();
            user.setName("AI");
            user.setId(Integer.MAX_VALUE);
        } else {
            int selectedUser = userList.getSelectedIndex();
            if (selectedUser == -1) {
                return;
            }
            user = connectedUsers.get(selectedUser);
            if (bindings.containsValue(user)) {
                return;
            }
        }
        TreePath selectedRole = scenarioTree.getSelectionPath();
        DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) selectedRole.getLastPathComponent();

        String roleName = (String) selectedNode.getUserObject();
        String parent = (String) ((DefaultMutableTreeNode) selectedRole.getParentPath().getLastPathComponent()).getUserObject();
        if (parent.equals(scenario.getName())
                && selectedRole.getParentPath().getParentPath() == null) {
            if (selectedNode.getParent().getChildAt(selectedNode.getParent().getChildCount() - 1).equals(selectedNode)) {
                return;
            }

            if (bindings.containsKey(roleName)) {
                return;
            }

            bindings.put(roleName, user);
            updateBindingsList();
        }
    }

    @Action
    public void start() {
        if (bindings.size() != scenario.getUsers().size() - 1) {
            return;
        }
        boolean willParticipate = false;
        RuntimeUser ru = null;
        for (User u : bindings.values()) {
            int id = u.getId() - 1;
            Message m = new Message(Message.SIM_START);
            m.setMessageText("WarfareSimulator");
            m.setScenario(scenario);
            Iterator<Entry<String, User>> it = bindings.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, User> entry = it.next();
                if (entry.getValue().equals(u)) {
                    for (User u2 : scenario.getUsers()) {
                        if (u2.getName().equals(entry.getKey())) {
                            m.setDestinationUserIndex(scenario.getUsers().indexOf(u2));
                            break;
                        }
                    }
                    break;
                }
            }
            if (u.getName().equals("AI")) {
                Scenario sec = new ScenarioHibernateDAO().getById(1);
                RuntimeUser ruAI = RuntimeUserFactory.getInstance().newRuntimeUser(sec.getUsers().get(m.getDestinationUserIndex()), sec);
                ruAI.setFederationName(m.getMessageText());
                ruAI.setAIControlled(true);
                Thread federateThread = new Thread(ruAI);
                federateThread.start();
            } else if (u.getId() != 0) {
                listener.getCasterAt(id).castMessage(m);
            } else {
                ru = RuntimeUserFactory.getInstance().newRuntimeUser(scenario.getUsers().get(m.getDestinationUserIndex()), scenario);
                ru.setFederationName(m.getMessageText());
                Thread federateThread = new Thread(ru);
                federateThread.start();
                willParticipate = true;
            }
        }
        RuntimeUser civilians = RuntimeUserFactory.getInstance().newRuntimeUser(scenario.getUsers().get(scenario.getUsers().size() - 1), scenario);
        civilians.setFederationName("WarfareSimulator");
        Thread federateThread = new Thread(civilians);
        federateThread.start();

        if (willParticipate) {
            PrototypePhase2UIView view = new PrototypePhase2UIView((SingleFrameApplication) Application.getInstance(), ru);
            Application.getInstance().show(view);
        }
    }

    private void updateBindingsList() {
        DefaultListModel model = new DefaultListModel();

        for (String u : bindings.keySet()) {
            model.addElement(u + " --> " + bindings.get(u).getName());
        }

        bindingList.setModel(model);
        bindingList.invalidate();
    }

    private void updateUserList() {
        DefaultListModel model = new DefaultListModel();

        for (User u : connectedUsers) {
            model.addElement(u.getName());
        }

        userList.setModel(model);
        userList.invalidate();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        jPanel1 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        scenarioTree = new javax.swing.JTree();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jPanel2 = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        userList = new javax.swing.JList();
        kickButton = new javax.swing.JButton();
        jPanel3 = new javax.swing.JPanel();
        listenButton = new javax.swing.JButton();
        listeningCheckBox = new javax.swing.JCheckBox();
        jLabel1 = new javax.swing.JLabel();
        portField = new javax.swing.JTextField();
        jPanel4 = new javax.swing.JPanel();
        jScrollPane3 = new javax.swing.JScrollPane();
        bindingList = new javax.swing.JList();
        bindButton = new javax.swing.JButton();
        deleteButton = new javax.swing.JButton();
        aiCheckBox = new javax.swing.JCheckBox();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
        statusPanel = new javax.swing.JPanel();
        javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();
        statusMessageLabel = new javax.swing.JLabel();
        statusAnimationLabel = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();

        mainPanel.setName("mainPanel"); // NOI18N
        mainPanel.setPreferredSize(new java.awt.Dimension(746, 600));

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(prototype.phase1ui.WarfareSimulator.class).getContext().getResourceMap(WarfareSimulatorView.class);
        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jPanel1.border.title"))); // NOI18N
        jPanel1.setName("jPanel1"); // NOI18N

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        scenarioTree.setModel(null);
        scenarioTree.setName("scenarioTree"); // NOI18N
        jScrollPane1.setViewportView(scenarioTree);

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(prototype.phase1ui.WarfareSimulator.class).getContext().getActionMap(WarfareSimulatorView.class, this);
        jButton1.setAction(actionMap.get("start")); // NOI18N
        jButton1.setText(resourceMap.getString("jButton1.text")); // NOI18N
        jButton1.setName("jButton1"); // NOI18N

        jButton2.setAction(actionMap.get("loadScenario")); // NOI18N
        jButton2.setName("jButton2"); // NOI18N

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 235, Short.MAX_VALUE)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addComponent(jButton1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 75, Short.MAX_VALUE)
                .addComponent(jButton2))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 381, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton1)
                    .addComponent(jButton2))
                .addContainerGap(108, Short.MAX_VALUE))
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jPanel2.border.title"))); // NOI18N
        jPanel2.setName("jPanel2"); // NOI18N

        jScrollPane2.setName("jScrollPane2"); // NOI18N

        userList.setName("userList"); // NOI18N
        jScrollPane2.setViewportView(userList);

        kickButton.setAction(actionMap.get("kick")); // NOI18N
        kickButton.setText(resourceMap.getString("kickButton.text")); // NOI18N
        kickButton.setName("kickButton"); // NOI18N

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 139, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(kickButton, javax.swing.GroupLayout.PREFERRED_SIZE, 62, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 212, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(kickButton)
                .addGap(182, 182, 182))
        );

        jPanel3.setName("jPanel3"); // NOI18N

        listenButton.setAction(actionMap.get("stopStartListening")); // NOI18N
        listenButton.setText(resourceMap.getString("listenButton.text")); // NOI18N
        listenButton.setName("listenButton"); // NOI18N

        listeningCheckBox.setText(resourceMap.getString("listeningCheckBox.text")); // NOI18N
        listeningCheckBox.setEnabled(false);
        listeningCheckBox.setName("listeningCheckBox"); // NOI18N

        jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
        jLabel1.setName("jLabel1"); // NOI18N

        portField.setText(resourceMap.getString("portField.text")); // NOI18N
        portField.setName("portField"); // NOI18N

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(listenButton)
                    .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 63, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(portField)
                    .addComponent(listeningCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap(27, Short.MAX_VALUE))
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addGap(4, 4, 4)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(portField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(listeningCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(listenButton))
                .addContainerGap(20, Short.MAX_VALUE))
        );

        jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jPanel4.border.title"))); // NOI18N
        jPanel4.setName("jPanel4"); // NOI18N

        jScrollPane3.setName("jScrollPane3"); // NOI18N

        bindingList.setName("bindingList"); // NOI18N
        jScrollPane3.setViewportView(bindingList);

        bindButton.setAction(actionMap.get("bind")); // NOI18N
        bindButton.setText(resourceMap.getString("bindButton.text")); // NOI18N
        bindButton.setName("bindButton"); // NOI18N

        deleteButton.setAction(actionMap.get("deleteBinding")); // NOI18N
        deleteButton.setText(resourceMap.getString("deleteButton.text")); // NOI18N
        deleteButton.setName("deleteButton"); // NOI18N

        aiCheckBox.setText(resourceMap.getString("aiCheckBox.text")); // NOI18N
        aiCheckBox.setName("aiCheckBox"); // NOI18N

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 153, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel4Layout.createSequentialGroup()
                        .addComponent(bindButton, javax.swing.GroupLayout.PREFERRED_SIZE, 61, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 27, Short.MAX_VALUE)
                        .addComponent(deleteButton))
                    .addComponent(aiCheckBox, javax.swing.GroupLayout.Alignment.LEADING))
                .addContainerGap())
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 212, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(bindButton)
                    .addComponent(deleteButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(aiCheckBox)
                .addContainerGap(252, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap(11, Short.MAX_VALUE))
        );
        mainPanelLayout.setVerticalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap())
                    .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(mainPanelLayout.createSequentialGroup()
                            .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addContainerGap())
                        .addGroup(mainPanelLayout.createSequentialGroup()
                            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addContainerGap()))))
        );

        menuBar.setName("menuBar"); // NOI18N

        fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
        fileMenu.setName("fileMenu"); // NOI18N

        exitMenuItem.setAction(actionMap.get("quit")); // NOI18N
        exitMenuItem.setName("exitMenuItem"); // NOI18N
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N
        aboutMenuItem.setName("aboutMenuItem"); // NOI18N
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        statusPanel.setName("statusPanel"); // NOI18N

        statusPanelSeparator.setName("statusPanelSeparator"); // NOI18N

        statusMessageLabel.setName("statusMessageLabel"); // NOI18N

        statusAnimationLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N

        progressBar.setName("progressBar"); // NOI18N

        javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(statusPanelSeparator, javax.swing.GroupLayout.DEFAULT_SIZE, 640, Short.MAX_VALUE)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(statusMessageLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 466, Short.MAX_VALUE)
                .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(statusAnimationLabel)
                .addContainerGap())
        );
        statusPanelLayout.setVerticalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addComponent(statusPanelSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(statusMessageLabel)
                    .addComponent(statusAnimationLabel)
                    .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(3, 3, 3))
        );

        setComponent(mainPanel);
        setMenuBar(menuBar);
        setStatusBar(statusPanel);
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JCheckBox aiCheckBox;
    private javax.swing.JButton bindButton;
    private javax.swing.JList bindingList;
    private javax.swing.JButton deleteButton;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JButton kickButton;
    private javax.swing.JButton listenButton;
    private javax.swing.JCheckBox listeningCheckBox;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JTextField portField;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JTree scenarioTree;
    private javax.swing.JLabel statusAnimationLabel;
    private javax.swing.JLabel statusMessageLabel;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JList userList;
    // End of variables declaration//GEN-END:variables
    private final Timer messageTimer;
    private final Timer busyIconTimer;
    private final Icon idleIcon;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;
    private JDialog aboutBox;
    private Listener listener;
    private Scenario scenario;
    private ArrayList<User> connectedUsers = new ArrayList<User>();
    private Map<String, User> bindings = new HashMap<String, User>();
    private User coordinator;
}
/*public URL[] addHibernateJars() {
URL[] urls = null;
try {
Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
addURL.setAccessible(true); //you're telling the JVM to override the
//default visibility
File[] files = getExternalHibernateJars(); //some method returning the jars to
//  add
ClassLoader cl = Thread.currentThread().getContextClassLoader();
urls = ((URLClassLoader) cl).getURLs().clone();
for (int i = 0; i < files.length; i++) {
URL url = files[i].toURI().toURL();
addURL.invoke(cl, new Object[]{url});
}
} catch (IllegalAccessException ex) {
Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalArgumentException ex) {
Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
} catch (MalformedURLException ex) {
Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchMethodException ex) {
Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
}
return urls;
}*/

/*public void addPorticoJar() {
try {
Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
addURL.setAccessible(true); //you're telling the JVM to override the
//default visibility
File file = getExternalPorticoJar(); //some method returning the jars to add

ClassLoader cl = Thread.currentThread().getContextClassLoader();

URL url = file.toURI().toURL();

addURL.invoke(ClassLoader.getSystemClassLoader(), new Object[]{url});
addURL.invoke(cl, new Object[]{url});


} catch (IllegalAccessException ex) {
Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalArgumentException ex) {
Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
} catch (MalformedURLException ex) {
Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchMethodException ex) {
Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(WarfareSimulatorView.class.getName()).log(Level.SEVERE, null, ex);
}
}*/

/*public void restoreClassLoader(URL[] urls) {

Thread.currentThread().setContextClassLoader(null);
System.gc();
System.gc();
System.gc();
System.gc();
System.gc();
URLClassLoader ucl = new URLClassLoader(urls);
Thread.currentThread().setContextClassLoader(ucl);


}*/

/*public File getExternalPorticoJar() {
File porticoJar = new File("extralib/portico.jar");
return porticoJar;
}*/

/*public File[] getExternalHibernateJars() {
String fileNames[] = {
"antlr-2.7.6.jar",
"asm-attrs.jar",
"asm.jar",
"cglib-2.1.3.jar",
"commons-collections-2.1.1.jar",
"dom4j-1.6.1.jar",
"ehcache-1.2.3.jar",
"ejb3-persistence.jar",
"hibernate-annotations.jar",
"hibernate-commons-annotations.jar",
"hibernate-entitymanager.jar",
"hibernate-tools.jar",
"hibernate3.jar",
"javassist.jar",
"jdbc2_0-stdext.jar",
"jta.jar",
"jtidy-r8-20060801.jar",
"commons-logging-1.1.jar"
};
File[] files = new File[fileNames.length];

for (int i = 0; i < files.length; i++) {
files[i] = new File("extralib/" + fileNames[i]);
}

return files;
}*/
